#include <stdlib.h>

#include "lib.h"
#include "pgsql.h"
#include "pggame.h"
#include "pgopts.h"
#include "pgsaved.h"
#include "odbc.h"
#include "missinggamenums.h"

PGPokerSQL::PGPokerSQL(const String& DBDSN, const String& DBLogin, const String& DBPassword)
	: TrackSQL(DBDSN, DBLogin, DBPassword)
{
#ifdef USE_MISSINGGAMENUMS
	//missing game nums deleted in TrackSQL::~TrackSQL
	missinggamenums = new MissingGameNums(this, "pub_getTableIdentityPaiGowPoker");
#endif
}

int32
PGPokerSQL::getOptions(PGPokerOpts* opts)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_PGPokerGetOptions ");

		if (query->exec())
		{
			int8 tinyint;

			while (query->getRow())
			{
				ok = query->getData(1, &tinyint);
				opts->useCommission = (int32)(tinyint != 0);
			}
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
PGPokerSQL::createGame(int32 casinoId,
	PID pid, bool8 forMoney, uint8 machid, int32 numCards, SESSIONID sessionId, int32 compFactor,
	PGPokerGameID gid, int32 bet, int32* balance, int32* comp)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_CreateGamePGPoker ");
		query->addParam(casinoId);
		query->addParam(pid, PIDLEN);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(machid, ODBCQuery::BINARY);
		query->addParam(numCards);
		query->addParam(sessionId, ODBCQuery::NOQUOTES);
		query->addParam(compFactor);
		query->addParam(bet, ODBCQuery::MONEY);

		if (query->exec())
		{
			while (query->getRow())
			{
				ok =
					query->getData(1, gid, PGPOKER_GAMEID_SIZE) &&
					query->getData(2, balance, ODBCQuery::MONEY) &&
					query->getData(3, comp);
			}
		}
		delete query;
	}
	delete conn;
	
	if (ok)
	{
#ifdef USE_MISSINGGAMENUMS
		int32 gamenum = atol(gid);
		if (missinggamenums)
			missinggamenums->setGameNum(gamenum);
#endif
	}

	return ok ? NoError : ExecFailed;
}


int32
PGPokerSQL::deal(PID pid, PGPokerGameID gid, int32 numPlayer, uint8* player)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_PGPokerDeal ");
		query->addParam(pid, PIDLEN);
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam(player, numPlayer, ODBCQuery::BINARY);  // kharmon. 11-07-06.  #8226.  Save player cards on deal, but not dealer cards.

		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}



int32
PGPokerSQL::gameDone(int32 casinoId,
	PID pid, bool8 forMoney, uint8 machid, 
	PGPokerGameID gid,
	int32 payout, int32 commission,
	int32* dealerTwoCard, int32* playerTwoCard,
	int32 dealerFiveCardJokerAsRank, int32 playerFiveCardJokerAsRank,
	int32 hiOutcome, int32 loOutcome, int32 gameOutcome,
	int32 balanceAdjust, int32* balance, int32* comp, 
    int32 numDealer, uint8* dealer,
	int32 numPlayer, uint8* player)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		uint8 twocard[2], jokerAsRank;

		query->define("exec pub_PGPokerGameDone ");
		query->addParam(casinoId);
		query->addParam(pid, PIDLEN);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(machid, ODBCQuery::BINARY);
		query->addParam(gid, ODBCQuery::NOQUOTES);

		twocard[0] = (uint8)(dealerTwoCard[0] & 0xff);
		twocard[1] = (uint8)(dealerTwoCard[1] & 0xff);
		query->addParam(twocard, 2, ODBCQuery::BINARY);

		twocard[0] = (uint8)(playerTwoCard[0] & 0xff);
		twocard[1] = (uint8)(playerTwoCard[1] & 0xff);
		query->addParam(twocard, 2, ODBCQuery::BINARY);

		jokerAsRank = (uint8)(dealerFiveCardJokerAsRank & 0xff);
		query->addParam(jokerAsRank, ODBCQuery::BINARY);

		jokerAsRank = (uint8)(playerFiveCardJokerAsRank & 0xff);
		query->addParam(jokerAsRank, ODBCQuery::BINARY);

		query->addParam((uint8)(hiOutcome & 0xffL), ODBCQuery::BINARY);
		query->addParam((uint8)(loOutcome & 0xffL), ODBCQuery::BINARY);
		query->addParam((uint8)(gameOutcome & 0xffL), ODBCQuery::BINARY);

		query->addParam(payout, ODBCQuery::MONEY);
		query->addParam(commission, ODBCQuery::MONEY);
		query->addParam(balanceAdjust, ODBCQuery::MONEY);

        // kharmon.  10-16-06.  #8226.  Only safe to save the cards when the game is done.
		query->addParam(dealer, numDealer, ODBCQuery::BINARY);
		query->addParam(player, numPlayer, ODBCQuery::BINARY);

		if (query->exec())
		{
			while (query->getRow())
			{
				ok = query->getData(1, balance, ODBCQuery::MONEY) &&
					query->getData(2, comp);
			}
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
PGPokerSQL::hasSavedGame(PID pid, bool8 forMoney, uint8 machid, PGPokerGameID gid,
	PGPokerSavedGame* dest, bool8* exists)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	*exists = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_PGPokerGetSavedGame ");
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(machid, ODBCQuery::BINARY);

		if (query->exec())
		{
			int32 hasSaved = 0;

			ok = true;

			while (query->getRow())
			{
				if (query->getData(1, &hasSaved) && hasSaved!=0)
				{
					int8 tinyint;

					*exists = true;

                    if(hasSaved==1)
                    {
                        // kharmon.  10-16-06.  #8226.  This is an older saved game that doesn't
                        // have a deckseed.
                        dest->bHasDeckSeed = false;
					    query->getData(2, gid, PGPOKER_GAMEID_SIZE);
					    query->getData(3, &dest->bet, ODBCQuery::MONEY);

					    query->getData(4, &tinyint);
					    dest->useCommission = (int32)(tinyint != 0);

					    query->getData(5, &tinyint);

					    query->getData(6, dest->dealerCards,
						    PGPokerSavedGame::MAXCARDS, &dest->numDealerCards);

					    query->getData(7, dest->playerCards,
						    PGPokerSavedGame::MAXCARDS, &dest->numPlayerCards);

					    dest->numDealerCards = dest->numPlayerCards = tinyint;
                    }
                    else if(hasSaved==2)
                    {
                        // kharmon.  10-16-06.  #8226.  This is a newer saved game record, which
                        // includes a deckseed for use in regenerating the cards.
                        dest->bHasDeckSeed = true;

					    query->getData(2, gid, PGPOKER_GAMEID_SIZE);
					    query->getData(3, &dest->bet, ODBCQuery::MONEY);

					    query->getData(4, &tinyint);
					    dest->useCommission = (int32)(tinyint != 0);

					    query->getData(5, &dest->nDeckSeed);
                    }
				}
			}
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
PGPokerSQL::removeSavedGame(PID pid, bool8 forMoney, uint8 machid)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_PGPokerRemoveSavedGame ");
		query->addParam(pid, PIDLEN);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(machid, ODBCQuery::BINARY);

		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
PGPokerSQL::saveGame(PID pid, bool8 forMoney, uint8 machid, PGPokerGameID gid,
	PGPokerSavedGame* src)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_PGPokerSaveGame ");
		query->addParam(pid, PIDLEN);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(machid, ODBCQuery::BINARY);
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam((bool8)(src->useCommission != 0));
        query->addParam(src->nDeckSeed);    // kharmon.  10-16-06.  #8226.  Save the deckseed here.  We'll use it to regenerate the cards if needed.

		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}
